export default class WebsocketClass {
    /**
    * @description 构造函数
    * @param {String} title 标题
    * @param {String} url  请求地址
    * @param {Object} sendData  发送信息
    * @param {Function} callback  回调函数
    * @param {Boolean} urlShow  是否xxx
    * @return {void}
    */
    constructor(title, url, sendData, callback, urlShow = true) {
        this.title = title
        this.url = url
        this.sendData = sendData
        this.callback = callback
        this.urlShow = urlShow


        this.wsObj = null // WebSocket 对象
        this.lockReconnect = false // 避免重复连接
        this.wsCreateHandler = null// 重连定时器
        this.timeout = 15000// 超时时间
        this.timeoutObj = null // 计时器对象——向后端发送心跳检测
        this.serverTimeoutObj = null // 计时器对象——等待后端心跳检测的回复

    }
    // 创建websocket
    createWebSocket() {
        if (typeof WebSocket === 'undefined') {
            console.warn('您的浏览器不支持WebSocket，无法获取数据')
            return false
        }
        const SplicingUrl = `ws://192.168.1.214:16223${this.url}`
        let webSocketLink = this.urlShow ? SplicingUrl : this.url

        try {
            this.wsObj = new WebSocket(webSocketLink)
            // 初始化 WebSocket 事件处理
            this.initWsEventHandle()
        } catch (e) {
            this.writeToScreen('连接错误，尝试重新连接！')
            this.reconnect()
        }
    }
    // 初始化 WebSocket 事件处理
    initWsEventHandle() {
        try {
            // 连接成功
            this.wsObj.onopen = event => {
                this.onWsOpen(event)
                this.reset().start()
            }

            // 监听服务器端返回的信息
            this.wsObj.onmessage = event => {
                this.onWsMessage(event)
                this.reset().start()
            }

            // 连接关闭
            this.wsObj.onclose = event => {
                this.onWsClose(event)
            }

            // 连接错误
            this.wsObj.onerror = event => {
                this.onWsError(event)
                this.reconnect()
            }
        } catch (err) {
            this.writeToScreen('事件绑定失败，尝试重新连接')
            this.reconnect()
        }
        // 监听窗口关闭事件，当窗口关闭时，主动去关闭websocket连接，防止连接还没断开就关闭窗口，server端会抛异常。
        window.onbeforeunload = () => {
            this.wsObj.close()
        }
    }
    // WebSocket 连接成功处理
    onWsOpen(event) {
        console.log(`${this.title}:WebSocket-连接成功:", ${event}`)
        if (this.wsObj.readyState === this.wsObj.OPEN) {
            this.wsObj.send(JSON.stringify(this.sendData))
        }
    }
    // WebSocket 收到消息处理
    onWsMessage(event) {
        console.log(event, this.title)
        if (event.data.indexOf('HeartBeat') > -1) {
            // 心跳回复——心跳检测重置
            // 收到心跳检测回复就说明连接正常
            console.log('收到心跳检测回复')
            // 心跳检测重置
            return
        }
        if (event.data === '连接成功') {return}
        // 普通推送——正常处理
        // 相关处理
        const jsonStr = event.data
        this.callback(jsonStr)
    }
    // WebSocket 关闭连接处理
    onWsClose() {
        this.writeToScreen('WebSocket:已关闭')
        // 心跳检测重置
        this.reset()
        this.wsObj.close()
    }
    // WebSocket 错误处理
    onWsError(event) {
        console.warn(' WebSocket 错误:', event)
    }
    // 将消息写入控制台
    writeToScreen(message) {
        console.warn(`${this.title}:${message}`)
    }
    // 心跳开始
    start() {
        // 开启定时器发送 ping 到后台
        this.timeoutObj = setTimeout(() => {
            this.sendPingToBackend()

            // 15s之内如果没有收到后台的消息，则认为连接断开了，需要重连
            this.serverTimeoutObj = setTimeout(() => {
                console.log('未收到心跳检测回复')
                this.reconnect()
            }, this.timeout)
        }, this.timeout)
    }
    // 心跳重置
    reset() {
        this.timeoutObj && clearTimeout(this.timeoutObj)
        this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj)
        return this
    }
    // 发送心跳检测
    sendPingToBackend() {
        if (this.wsObj && this.wsObj.readyState === this.wsObj.OPEN) {
            const data = { ping: true }
            this.wsObj.send(JSON.stringify(data))
            console.log('发送心跳检测')
        }
    }
    // 关闭 WebSocket
    closeWebSocket() {
        if (this.wsObj) {
            this.reset()
            this.wsObj.close()
            this.lockReconnect = true
            this.wsCreateHandler && clearTimeout(this.wsCreateHandler)
        }
    }
    // 重新连接
    reconnect() {
        if (this.lockReconnect) {return}
        this.writeToScreen('3 秒后重 连')
        this.lockReconnect = true
        this.wsCreateHandler && clearTimeout(this.wsCreateHandler)
        this.wsCreateHandler = setTimeout(() => {
            this.writeToScreen('重新连接中...')
            this.lockReconnect = false
            this.createWebSocket()
            this.writeToScreen('重新连接完成')
        }, 3000)
    }
}